using System;
using GameFramework;
using UnityEngine;
using UnityGameFramework.Runtime;

namespace LS.SVariable
{
    public class SavingAssociatedVariableUtil
    {
        public static SavingAssociatedVariable CreateOrGet<T>(string name, string savingGroupName)
        {
            DataNodeComponent dataNode = LSEntry.DataNode;
            SavingComponent saving = LSEntry.Saving;
            SavingAssociatedVariable variable = null;
            
            if (LSEntry.DataNode == null || dataNode == null)
            {
                Type type = typeof(T);
                if (type.IsPrimitive)
                {
                    variable = CreateForPrimitive(type);
                }
                else
                {
                    variable = CreateForAny<T>();
                }
                
            }

            if (variable != null)
            {
                variable.Initialize(savingGroupName, name);
            }
            return variable;
        }
        
        public static SavingAssociatedVariable CreateOrGet(Type type, string name, string savingGroupName)
        {
            DataNodeComponent dataNode = LSEntry.DataNode;
            SavingAssociatedVariable variable = null;
            
            if (LSEntry.DataNode == null || dataNode == null)
            {
                if (type.IsPrimitive)
                {
                    variable = CreateForPrimitive(type);
                }
                else if (type.IsValueType)
                {
                    variable = CreateForStruct(type);
                }
                else
                {
                    variable = CreateForAny();
                }
                
            }
            if (variable != null)
            {
                variable.Initialize(savingGroupName, name);
            }
            return variable;
        }
        
        internal static SavingAssociatedVariable CreateForPrimitive(Type type)
        {
            SavingAssociatedVariable variable = null;
            if (type == typeof(string))
            {
                variable =  ReferencePool.Acquire<StringSVar>();
            }
            else if (type ==  typeof(char))
            {
                variable =  ReferencePool.Acquire<CharSVar>();
            }
            else if (type ==  typeof(bool))
            {
                variable =  ReferencePool.Acquire<BoolSVar>();
            }
            else if (type == typeof(byte))
            {
                variable =  ReferencePool.Acquire<ByteSVar>();
            }
            else if (type == typeof(decimal))
            {
                variable =  ReferencePool.Acquire<DecimalSVar>();
            }
            else if (type == typeof(double))
            {
                variable =  ReferencePool.Acquire<DoubleSVar>();
            }
            else if (type == typeof(float))
            {
                variable =  ReferencePool.Acquire<FloatSVar>();
            }
            else if (type == typeof(int))
            {
                variable =  ReferencePool.Acquire<IntSVar>();
            }
            else if (type == typeof(uint))
            {
                variable =  ReferencePool.Acquire<UIntSVar>();
            }
            else if (type == typeof(long))
            {
                variable =  ReferencePool.Acquire<LongSVar>();
            }
            else if (type == typeof(ulong))
            {
                variable = ReferencePool.Acquire<ULongSVar>();
            }
            else if (type == typeof(short))
            {
                variable = ReferencePool.Acquire<ShortSVar>();
            }
            else if (type == typeof(ushort))
            {
                variable = ReferencePool.Acquire<UShortSVar>();
            }
            else if (type == typeof(sbyte))
            {
                variable =  ReferencePool.Acquire<SByteSVar>();
            }
            else
            {
                variable = CreateForAny();
            }
            return variable;
        }
        
        internal static SavingAssociatedVariable CreateForStruct(Type type)
        {
            SavingAssociatedVariable variable = null;
            if (type == typeof(Rect))
            {
                variable =  CreateForAny<Rect>();
            }
            else if (type == typeof(RectInt))
            {
                variable =  CreateForAny<RectInt>();
            }
            else if (type == typeof(Vector2))
            {
                variable =  CreateForAny<Vector2>();
            }
            else if (type == typeof(Vector2Int))
            {
                variable =  CreateForAny<Vector2Int>();
            }
            else if (type == typeof(Vector3))
            {
                variable =  CreateForAny<Vector3>();
            }
            else if (type == typeof(Vector3Int))
            {
                variable =  CreateForAny<Vector3Int>();
            }
            else if (type == typeof(Vector4))
            {
                variable =  CreateForAny<Vector4>();
            }
            else if (type == typeof(Bounds))
            {
                variable =  CreateForAny<Bounds>();
            }
            else if (type == typeof(BoundsInt))
            {
                variable =  CreateForAny<BoundsInt>();
            }
            else if (type == typeof(Matrix4x4))
            {
                variable =  CreateForAny<Matrix4x4>();
            }
            else if (type == typeof(Color))
            {
                variable =  CreateForAny<Color>();
            }
            else if (type == typeof(Color32))
            {
                variable =  CreateForAny<Color32>();
            }
            else if (type == typeof(Quaternion))
            {
                variable =  CreateForAny<Quaternion>();
            }
            else
            {
                variable = CreateForAny();
            }
            return variable;
        }
        
        internal static SavingAssociatedVariable CreateForAny<T>()
        {
            SavingAssociatedVariable variable = ReferencePool.Acquire<CompoundSVar<T>>();
            return variable;
        }
        
        internal static SavingAssociatedVariable CreateForAny()
        {
            SavingAssociatedVariable variable = ReferencePool.Acquire<ObjectSVar>();
            return variable;
        }
    }
}
